package models

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log"

	"github.com/elastic/go-elasticsearch/v8"
	"github.com/elastic/go-elasticsearch/v8/esapi"
)

type User struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

var es *elasticsearch.Client

func init() {
	var err error
	cfg := elasticsearch.Config{
		Addresses: []string{
			"http://localhost:9200",
		},
	}

	es, err = elasticsearch.NewClient(cfg)
	if err != nil {
		log.Fatalf("Error creating Elasticsearch client: %s", err)
	}

	// 测试连接
	res, err := es.Info()
	if err != nil {
		log.Fatalf("Error getting Elasticsearch info: %s", err)
	}
	defer res.Body.Close()

	log.Println("Successfully connected to Elasticsearch")

	// 创建索引
	createIndex()
}

func createIndex() {
	// 检查索引是否存在
	res, err := es.Indices.Exists([]string{"users"})
	if err != nil {
		log.Printf("Error checking index existence: %s", err)
		return
	}
	defer res.Body.Close()

	if res.StatusCode == 404 {
		// 创建索引
		createRes, err := es.Indices.Create("users")
		if err != nil {
			log.Printf("Error creating index: %s", err)
			return
		}
		defer createRes.Body.Close()

		if createRes.IsError() {
			log.Printf("Error creating index: %s", createRes.String())
		} else {
			log.Println("Successfully created 'users' index")
		}
	}
}

func AddUser(user *User) error {
	// 将用户数据转换为JSON
	userJSON, err := json.Marshal(user)
	if err != nil {
		return fmt.Errorf("error marshaling user: %s", err)
	}

	// 创建文档
	req := esapi.IndexRequest{
		Index:      "users",
		DocumentID: user.ID,
		Body:       bytes.NewReader(userJSON),
		Refresh:    "true",
	}

	res, err := req.Do(context.Background(), es)
	if err != nil {
		return fmt.Errorf("error indexing document: %s", err)
	}
	defer res.Body.Close()

	if res.IsError() {
		return fmt.Errorf("error indexing document: %s", res.String())
	}

	log.Printf("Successfully added user: %s (%s)", user.Name, user.ID)
	return nil
}

func GetUserByID(id string) (*User, error) {
	req := esapi.GetRequest{
		Index:      "users",
		DocumentID: id,
	}

	res, err := req.Do(context.Background(), es)
	if err != nil {
		return nil, fmt.Errorf("error getting document: %s", err)
	}
	defer res.Body.Close()

	if res.StatusCode == 404 {
		return nil, nil // 用户不存在
	}

	if res.IsError() {
		return nil, fmt.Errorf("error getting document: %s", res.String())
	}

	var result map[string]interface{}
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("error parsing response: %s", err)
	}

	source, ok := result["_source"].(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("invalid document structure")
	}

	user := &User{
		ID:   getString(source, "id"),
		Name: getString(source, "name"),
	}

	return user, nil
}

func GetAllUsers() ([]User, error) {
	var buf bytes.Buffer
	query := map[string]interface{}{
		"query": map[string]interface{}{
			"match_all": map[string]interface{}{},
		},
	}

	if err := json.NewEncoder(&buf).Encode(query); err != nil {
		return nil, fmt.Errorf("error encoding query: %s", err)
	}

	res, err := es.Search(
		es.Search.WithIndex("users"),
		es.Search.WithBody(&buf),
		es.Search.WithSize(1000),
	)
	if err != nil {
		return nil, fmt.Errorf("error searching documents: %s", err)
	}
	defer res.Body.Close()

	if res.IsError() {
		return nil, fmt.Errorf("error searching documents: %s", res.String())
	}

	var result map[string]interface{}
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("error parsing response: %s", err)
	}

	hits, ok := result["hits"].(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("invalid response structure")
	}

	hitsArray, ok := hits["hits"].([]interface{})
	if !ok {
		return []User{}, nil // 没有用户数据
	}

	var users []User
	for _, hit := range hitsArray {
		hitMap, ok := hit.(map[string]interface{})
		if !ok {
			continue
		}

		source, ok := hitMap["_source"].(map[string]interface{})
		if !ok {
			continue
		}

		user := User{
			ID:   getString(source, "id"),
			Name: getString(source, "name"),
		}
		users = append(users, user)
	}

	return users, nil
}

func UserExists(id, name string) (bool, error) {
	var buf bytes.Buffer
	query := map[string]interface{}{
		"query": map[string]interface{}{
			"bool": map[string]interface{}{
				"must": []map[string]interface{}{
					{"term": map[string]interface{}{"id": id}},
					{"term": map[string]interface{}{"name": name}},
				},
			},
		},
	}

	if err := json.NewEncoder(&buf).Encode(query); err != nil {
		return false, fmt.Errorf("error encoding query: %s", err)
	}

	res, err := es.Search(
		es.Search.WithIndex("users"),
		es.Search.WithBody(&buf),
		es.Search.WithSize(1),
	)
	if err != nil {
		return false, fmt.Errorf("error searching user: %s", err)
	}
	defer res.Body.Close()

	if res.IsError() {
		return false, fmt.Errorf("error searching user: %s", res.String())
	}

	var result map[string]interface{}
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		return false, fmt.Errorf("error parsing response: %s", err)
	}

	hits, ok := result["hits"].(map[string]interface{})
	if !ok {
		return false, nil
	}

	total, ok := hits["total"].(map[string]interface{})
	if !ok {
		return false, nil
	}

	count, ok := total["value"].(float64)
	if !ok {
		return false, nil
	}

	return count > 0, nil
}

func getString(data map[string]interface{}, key string) string {
	if value, ok := data[key]; ok {
		if str, ok := value.(string); ok {
			return str
		}
	}
	return ""
}

// 初始化测试数据
func InitTestData() {
	testUsers := []User{
		{ID: "1", Name: "张三"},
		{ID: "2", Name: "李四"},
		{ID: "3", Name: "王五"},
	}

	for _, user := range testUsers {
		exists, err := UserExists(user.ID, user.Name)
		if err != nil {
			log.Printf("Error checking user existence: %s", err)
			continue
		}

		if !exists {
			err := AddUser(&user)
			if err != nil {
				log.Printf("Failed to add test user %s: %v", user.Name, err)
			} else {
				log.Printf("Added test user: %s (%s)", user.Name, user.ID)
			}
		}
	}
}
